﻿// -----------------------------------------------------------------------
// <copyright file="FormsManager.cs" company="Abyssalsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Gui.Presentation
{
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Text;
    using System.Windows.Forms;
    using System.Xml;
    using Core.Player;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public static class FormsManager
    {
        private static List<Form> MetalForms = new List<Form>();

        /// <summary>Our video form</summary>
        private static Form video;

        /// <summary>Our audio form</summary>
        private static Form audio;

        public static EventHandler SwitchAudioVideoStyle;

        private static Metal.Tasks.TaskManager taskManager;
 
        /// <summary>
        /// Gets or sets the main form (audio / video)
        /// </summary>
        public static Form AudioForm
        {
            get
            {
                return audio;
            }
            set
            {
                audio = value;
            }
        }

        /// <summary>
        /// Gets or sets the main form (audio / video)
        /// </summary>
        public static Form VideoForm
        {
            get
            {
                return video;
            }
            set
            {
                video = value;
            }
        }

        private static PlayerStyle currentPlayerStyle;

        public static PlayerStyle CurrentPlayerStyle
        {
            get
            {
                return currentPlayerStyle;
            }
            set
            {
                currentPlayerStyle = value;
            }
        }

        /// <summary>Player layout</summary>
        public enum PlayerStyle
        {
            /// <summary>Audio style</summary>
            Audio,

            /// <summary>Video style</summary>
            Video
        }

        /// <summary>
        /// Save player style
        /// </summary>
        /// <param name="style">The style of the player: audio / video</param>
        public static void SavePlayerStyle()
        {
            try
            {
                if (CurrentPlayerStyle == PlayerStyle.Audio)
                {
                    Metal.Config.Settings.Instance.SetValue("LastSettings.MainFormStyle", "Audio");
                    Metal.Config.ThemeSettings.Instance.SetValue("Config.Audio.MainForm.Visible", true);
                    Metal.Config.ThemeSettings.Instance.SetValue("Config.Audio.VideoForm.Visible", false);
                }
                else
                {
                    Metal.Config.Settings.Instance.SetValue("LastSettings.MainFormStyle", "Video");
                    Metal.Config.ThemeSettings.Instance.SetValue("Config.Audio.MainForm.Visible", false);
                    Metal.Config.ThemeSettings.Instance.SetValue("Config.Audio.VideoForm.Visible", true);
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Get a Metal player form
        /// </summary>
        /// <param name="formName">The form name</param>
        /// <returns>Returns form, or null if is not found</returns>
        public static Form GetForm(string formName)
        {
            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            foreach (Form form in Application.OpenForms)
            {
                if (form.Name == formName)
                {
                    return form;
                }
            }
            
            return null;
        }

        /// <summary>
        /// Brings to front all current open forms
        /// </summary>
        public static void BringAllToFront()
        {
            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            foreach (Form form in Application.OpenForms)
            {
                form.BringToFront();
            }
        }

        /// <summary>
        /// Set form owner
        /// </summary>
        /// <param name="ownerForm">The owner form</param>
        public static void SetOwnerForm(Form ownerForm)
        {
            try
            {
                Assembly currentAssembly = Assembly.GetExecutingAssembly();
                foreach (Form form in Application.OpenForms)
                {
                    form.Owner = null;
                    if (form.Name != ownerForm.Name && form.Name != "MainForm" && form.IsDisposed == false)
                    {
                        form.Owner = ownerForm;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Set for owner
        /// </summary>
        /// <param name="ownerForm">The owner form name</param>
        public static void SetOwnerForm(string style)
        {
            RemoveOwnerForm();

            if (style == "MainForm")
            {
                Assembly currentAssembly = Assembly.GetExecutingAssembly();
                foreach (Form form in Application.OpenForms)
                {
                    if (form.Name != "MainForm")
                    {
                        form.Owner = AudioForm;
                    }
                    else
                    {
                        SwitchAudioVideoStyle(null, null);
                    }
                }
            }
            else
            {
                Assembly currentAssembly = Assembly.GetExecutingAssembly();
                foreach (Form form in Application.OpenForms)
                {
                    if (form.Name != "VideoForm")
                    {
                        form.Owner = VideoForm;
                    }
                    else
                    {
                        SwitchAudioVideoStyle(null, null);
                    }
                }
            }
        }

        /// <summary>
        /// Remove owner form for all Metal windows
        /// </summary>
        public static void RemoveOwnerForm()
        {
            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            foreach (Form form in Application.OpenForms)
            {
                form.Owner = null;
            }
        }

        /// <summary>
        /// Main entry point. This loads Metal Player forms
        /// </summary>
        public static void LoadMetalPlayer(string shellFile)
        {
            try
            {
                if (Metal.Config.Settings.Instance.GetValue("LastSettings.MainFormStyle", "Audio") == "Audio")
                {
                    CurrentPlayerStyle = PlayerStyle.Audio;
                }
                else
                {
                    CurrentPlayerStyle = PlayerStyle.Video;
                }

                XmlNodeList forms = Metal.Config.ThemeSettings.Instance.GetForms();
                foreach (XmlNode form in forms)
                {
                    Form newForm = Metal.Controller.Accesibility.CreateFormInstance(form.Attributes["formNamespace"].Value, form.Attributes["className"].Value);

                    if (form.Name == "VideoForm")
                    {
                        video = newForm;
                    }
                    if (form.Name == "AudioForm")
                    {
                        audio = newForm;
                    }
                    MetalForms.Add(newForm);
                }

                if (Metal.Controller.Accesibility.GetFormInstance("MainForm").Visible == true)
                {
                    Gui.Presentation.FormsManager.SetOwnerForm("MainForm");
                }
                else
                {
                    Gui.Presentation.FormsManager.SetOwnerForm("VideoForm");
                }

                // Subscribe to on media load event (used to switch between audio / video style)
                Core.Player.Events.Instance.Open += new EventHandler(OnOpenFile);

                if (shellFile != null)
                {
                    Core.Player.Playback.Instance.Open(shellFile);
                    Core.Player.Playback.Instance.Play();
                }

                // Now... let's start the tasks defined in Tasks.xml config file
                taskManager = new Metal.Tasks.TaskManager();
                taskManager.LoadTasks();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Switch to video style if opened file is a video format
        /// </summary>
        /// <param name="sender">Object sender</param>
        /// <param name="e">Event args</param>
        private static void OnOpenFile(object sender, EventArgs e)
        {
            try
            {
                if (Gui.Presentation.FormsManager.GetForm("MainForm").WindowState == FormWindowState.Minimized ||
                    Gui.Presentation.FormsManager.GetForm("VideoForm").WindowState == FormWindowState.Minimized)
                {
                    // If the player is minimized, it will crash if we try to change the style. So, we ignore this and we will give up with layout switching.
                    // TODO: set here a bolean "toBeRestored" or something, and call the above code (after return) to switch the layout only when the player
                    // is restored from minimized mode.
                    return;
                }

                if (MediaInfo.CurrentFile == Helper.FileTypeEnum.LocalVideo || MediaInfo.CurrentFile == Helper.FileTypeEnum.InternetVideoStream)
                {
                    SwitchStyle(false);
                }
                else if (MediaInfo.CurrentFile == Helper.FileTypeEnum.LocalAudio || MediaInfo.CurrentFile == Helper.FileTypeEnum.InternetAudioStream)
                {
                    SwitchStyle(true);
                }
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }

        /// <summary>
        /// Switches player style (audio / video)
        /// </summary>
        /// <param name="audio">Set to true if you want to set the audio style, or false for video</param>
        public static void SwitchStyle(bool audioStyle)
        {
            try
            {
                if (audioStyle == false)
                {
                    if (VideoForm == null)
                    {
                        VideoForm = Metal.Controller.Accesibility.CreateFormInstance("Gui.Player", "Gui.Player.Main.VideoForm");
                    }

                    Gui.Presentation.FormsManager.SetOwnerForm("VideoForm");
                    VideoForm.Show();
                    VideoForm.ShowInTaskbar = true;
                    audio.Visible = false;
                    CurrentPlayerStyle = PlayerStyle.Video;
                }
                else
                {
                    Gui.Presentation.FormsManager.GetForm("MainForm").Visible = true;
                    Gui.Presentation.FormsManager.SetOwnerForm("MainForm");
                    if (VideoForm != null)
                    {
                        VideoForm.Visible = false;
                    }

                    CurrentPlayerStyle = PlayerStyle.Audio;
                }

                SavePlayerStyle();
            }
            catch (Exception ex)
            {
                Metal.User.UserMessage.ShowError(ex);
            }
        }
    }
}
